import {get, set} from "./store"
import {base} from "./base.ts";
import {walk} from "./treeUtil.ts";

export type ProxyAuthInfo = {
    username: string,
    password: string,
}

export interface ProxyServer extends chrome.proxy.ProxyServer {
    auth?: ProxyAuthInfo
    scheme: 'direct' | 'http' | 'https' | 'socks4' | 'socks5'
}

export function sanitizeProxyServer(v: ProxyServer): chrome.proxy.ProxyServer {
    return {
        host: v.host,
        port: v.port
    }
}

type ProxyConfigMeta = {
    profileID: string,
    color: string,
    profileName: string,
    pacScript: chrome.proxy.PacScript
}

export type ProxyConfigSimple = ProxyConfigMeta & {
    proxyType: 'proxy' | 'pac',
    proxyRules: {
        default: ProxyServer,
        http?: ProxyServer,
        https?: ProxyServer,
        ftp?: ProxyServer,
        bypassList: string[]
    },
    pacScript: chrome.proxy.PacScript
}

export type ProxyConfigPreset = ProxyConfigMeta & {
    proxyType: 'system' | 'direct'
}

export type ProfileConfig = ProxyConfigSimple | ProxyConfigPreset


export const SystemProfile: Record<string, ProfileConfig> = {
    DIRECT: {
        profileID: '367DEDBC-6750-4454-8321-4E4B088E20B1',
        color: '#7ad39e',
        profileName: 'DIRECT',
        proxyType: 'direct',
        pacScript: {}
    },
    SYSTEM: {
        profileID: '4FDEF36F-F389-4AF3-9BBC-B2E01B3B09E6',
        color: '#0430ff',
        profileName: 'SYSTEM', // no name needed for `system`
        proxyType: 'system',
        pacScript: {}
    },
    TERMIUS_PLUS: {
        profileID: 'termius-plus',
        color: '#00152a',
        profileName: 'TERMIUS_PLUS', // no name needed for `system`
        proxyType: 'pac',
        proxyRules: {
            default: {
                host: '127.0.0.1',
                auth: {
                    username: '',
                    password: ''
                },
                scheme: 'http',
            },
            bypassList: []
        },
        pacScript: {
            data: `let a ='www.google.com' ;function FindProxyForURL(url, host) {
  
  if (host === a) {
    return 'PROXY 127.0.0.1:7890; DIRECT';
  }  
  if (host === 'www.youtube.com') {
    return 'PROXY 127.0.0.1:7890; DIRECT';
  }
    if (host === 'open.sclecb.cn') {
    return 'PROXY 127.0.0.1:7890; DIRECT';
  }
  
  return 'DIRECT';
}`
        }
    },
}

export const initTermiusPlusPac = async () => {
    let res = await fetch(base + "/api-admin/application/list");

    let data = await res.json();

    let map: Record<string, string> = {}
    walk(data, (item: any) => {
        if (!item.isGroup) {
            if (item.proxy) {
                let host = item.content.toString()
                if (host.startsWith('http://')) {
                    host = host.slice(7)
                }
                if (host.startsWith('https://')) {
                    host = host.slice(8)
                }
                //过滤端口
                let index = host.indexOf(':')
                if (index !== -1) {
                    host = host.slice(0, index)
                }

                if (item.proxy.type === 'SOCKET5') {
                    map[host] = `SOCKS5 ${item.proxy.ip}:${item.proxy.port}; DIRECT`;
                } else {
                    map[host] = `PROXY ${item.proxy.ip}:${item.proxy.port}; DIRECT`;
                }
            }
        }
    })

    let pac = `
        let map = ${JSON.stringify(map)}
        function FindProxyForURL(url, host) {
            let proxy = map[host];
            if (proxy) {
                return proxy;
            }
            return 'DIRECT';
        }
        `

    console.log('初始化pac脚本', pac)

    SystemProfile.TERMIUS_PLUS.pacScript.data = pac;

}

initTermiusPlusPac()

const keyProfileStorage = 'profiles'
export type ProfilesStorage = {
    [key: string]: ProfileConfig
}
const onProfileUpdateListeners: ((p: ProfilesStorage) => void)[] = []

export async function listProfiles(): Promise<ProfilesStorage> {
    const s = await get<ProfilesStorage>(keyProfileStorage)
    return s || {}
}

export function onProfileUpdate(callback: (p: ProfilesStorage) => void) {
    onProfileUpdateListeners.push(callback)
}

async function overwriteProfiles(profiles: ProfilesStorage) {
    await set(keyProfileStorage, profiles)
    onProfileUpdateListeners.map(cb => cb(profiles))
}

export async function saveProfile(profile: ProfileConfig) {
    const data = await listProfiles()
    data[profile.profileID] = profile
    await overwriteProfiles(data)
}

export async function getProfile(profileID: string): Promise<ProfileConfig | undefined> {
    const data = await listProfiles()
    return data[profileID]
}

export async function deleteProfile(profileID: string) {
    const data = await listProfiles()
    delete data[profileID]
    await overwriteProfiles(data)
}